import csv
import shutil
import os

import fitz  # PyMuPDF
from docx import Document
from docx.shared import Inches
import io


from util.util_docx import DocxExtractor
from util.util_pdf import PdfExtractor


def copy_file_to_directory(file_path, path_dir_dst):
    """
    将指定的文件复制到目标文件夹。
    :param file_path: 要复制的文件的路径
    :param path_dir_dst: 目标文件夹的路径
    """
    # 确保目标文件夹存在
    if not os.path.exists(path_dir_dst):
        print("path_dir_dst not exist! path_dir_dst:", path_dir_dst)
        return
        # os.makedirs(path_dir_dst)
    # 构建目标文件的完整路径
    file_name = os.path.basename(file_path)
    destination_path = os.path.join(path_dir_dst, file_name)
    # 复制文件
    try:
        shutil.copy2(file_path, destination_path)
        print(f"destination_path: {destination_path}, File {file_name} copied to {path_dir_dst}")
    except Exception as e:
        print(f"Failed to copy {file_name}: {e}")


# 获取筛选分数列
# keyword = ['score_ai_part_3', 'score_ai_part_4', 'score_ai_part_5', 'score_ai_part_6', 'score_ai_part_7']
def select_score0_from_csv(csv_file, keyword):
    record_list = []
    # 打开并读取CSV文件
    with open(csv_file, mode='r', encoding='utf-8') as file:
        reader = csv.DictReader(file)
        # 遍历每一行
        for row in reader:
            # 检查'score_ai_part_4'是否以"0-"开头
            if row[keyword].startswith('0-'):
                # 打印对应的'file_path'
                # print(row['file_path'])
                record_list.append(row)
    return record_list


def save_paragraphs_2_docx(path_docx, paragraphs, section_name):
    """
    将字符串列表中的每个元素作为一段添加到指定的 .docx 文件中，并在文档中添加一个小结标题。

    :param path_docx: .docx 文件的保存路径
    :param paragraphs: 包含多个段落的字符串列表
    :param section_name: 小结的标题
    """
    # 尝试打开现有文档，如果不存在则创建新文档
    try:
        doc = Document(path_docx)
    except:
        doc = Document()
    # 添加小结标题
    doc.add_heading(section_name, level=1)
    # 遍历每个段落并添加到文档中
    for paragraph in paragraphs:
        doc.add_paragraph(paragraph)
        print(paragraph)
    # 保存文档
    doc.save(path_docx)
    print(f"Paragraphs saved to {path_docx}")


def extract_and_save_content_docx(src_docx, dst_docx, start_heading, end_heading, section_name):
    """
    从源 .docx 文件中提取指定标题之间的内容，并保存到新的 .docx 文件中。

    :param src_docx: 源 .docx 文件的路径
    :param dst_docx: 目标 .docx 文件的路径
    :param start_heading: 开始的小结标题
    :param end_heading: 结束的小结标题
    :param section_name: 小结的标题
    """
    # 读取源文档
    src_doc = Document(src_docx)
    # 打开目标文档: 尝试打开现有文档，如果不存在则创建新文档
    try:
        dst_doc = Document(dst_docx)
    except:
        dst_doc = Document()
    # 目标文档添加小结标题
    dst_doc.add_heading(section_name, level=1)
    # 标记是否在指定标题之间
    in_target_section = False
    # 遍历文档中的所有元素
    for element in src_doc.element.body:
        if element.tag.endswith('p'):  # 处理段落
            paragraph = element
            text = ''.join(run.text for run in paragraph.findall('.//w:t', namespaces={
                'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}))
            # 检查段落文本中是否包含开始标志
            if start_heading in text and "........." not in text:
                in_target_section = True
            elif end_heading in text and "........." not in text:
                in_target_section = False
            if in_target_section:
                # 添加开始标志到新文档中
                dst_doc.add_paragraph(text)
        elif element.tag.endswith('pic:pic'):  # 处理图片
            if in_target_section:
                # 获取图片的二进制数据
                blip = element.xpath('.//a:blip',
                                     namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})[0]
                image_data = blip.attrib['r:embed']
                image_part = src_doc.part.related_parts[image_data]
                # 将图片添加到新文档中
                dst_doc.add_picture(image_part.image.blob, width=Inches(1.25))

    # 保存目标文档
    dst_doc.save(dst_docx)
    print(f"Content extracted and saved to {dst_docx}")


def extract_and_save_content_docx_bak(src_docx, dst_docx, start_heading, end_heading, section_name):
    """
    从源 .docx 文件中提取指定标题之间的内容，并保存到新的 .docx 文件中。

    :param src_docx: 源 .docx 文件的路径
    :param dst_docx: 目标 .docx 文件的路径
    :param start_heading: 开始的小结标题
    :param end_heading: 结束的小结标题
    :param section_name: 小结的标题
    """
    # 读取源文档
    src_doc = Document(src_docx)
    # 打开目标文档: 尝试打开现有文档，如果不存在则创建新文档
    try:
        dst_doc = Document(dst_docx)
    except:
        dst_doc = Document()
    # 目标文档添加小结标题
    dst_doc.add_heading(section_name, level=1)
    # 标记是否在指定标题之间
    in_target_section = False
    # 遍历文档中的所有元素
    for element in src_doc.element.body:
        if element.tag.endswith('p'):  # 处理段落
            paragraph = element.text
            if paragraph == start_heading:
                in_target_section = True
                continue
            elif paragraph == end_heading:
                break

            if in_target_section:
                dst_doc.add_paragraph(paragraph)

        # elif element.tag.endswith('tbl'):  # 处理表格
        #     if in_target_section:
        #         table = element.getchildren()
        #         new_table = dst_doc.add_table(rows=len(table), cols=len(table[0]))
        #         for i, row in enumerate(table):
        #             for j, cell in enumerate(row):
        #                 new_table.cell(i, j).text = cell.text

        elif element.tag.endswith('pic:pic'):  # 处理图片
            if in_target_section:
                # 获取图片的二进制数据
                blip = element.xpath('.//a:blip')[0]
                rId = blip.attrib['r:embed']
                image_part = src_doc.part.related_parts[rId]
                image_data = image_part.blob

                # 添加图片到目标文档
                dst_doc.add_picture(io.BytesIO(image_data), width=Inches(4.0))

    # 保存目标文档
    dst_doc.save(dst_docx)
    print(f"Content extracted and saved to {dst_docx}")


def extract_and_save_content_pdf(src_pdf, dst_docx, start_heading, end_heading, section_name):
    """
    从源 .pdf 文件中提取指定标题之间的内容，并保存到新的 .docx 文件中。

    :param src_pdf: 源 .pdf 文件的路径
    :param dst_docx: 目标 .docx 文件的路径
    :param start_heading: 开始的小结标题
    :param end_heading: 结束的小结标题
    :param section_name: 小结的标题
    """
    # 读取源 PDF 文件
    pdf_document = fitz.open(src_pdf)
    # 打开目标文档: 尝试打开现有文档，如果不存在则创建新文档
    try:
        dst_doc = Document(dst_docx)
    except:
        dst_doc = Document()
    # 目标文档添加小结标题
    dst_doc.add_heading(section_name, level=1)
    # 标记是否在指定标题之间
    in_target_section = False
    # 遍历pdf
    for page in pdf_document:
        # 处理页面中文字
        text = page.get_text("text")
        text = text.replace(" ", "")
        lines = text.split('\n')
        for line in lines:
            # 检查是否是我们关心的标题, 排除目录
            if start_heading in line and "........." not in line:
                in_target_section = True
            elif end_heading in line and "........." not in line:
                in_target_section = False
            elif in_target_section:
                # 如果当前有正在处理的标题，将内容添加到word
                dst_doc.add_paragraph(line)
        # 处理页面中的图片
        if in_target_section:
            images = page.get_images(full=True)
            for img_index, img in enumerate(images):
                try:
                    xref = img[0]
                    base_image = pdf_document.extract_image(xref)
                    image_bytes = base_image["image"]
                    image_stream = io.BytesIO(image_bytes)
                    dst_doc.add_picture(image_stream)
                except Exception as e:
                    print(f"pdf保存图片出错: {e}")
    dst_doc.save(dst_docx)
    print(f"Content extracted and saved to {dst_docx}")


def process_part4(csv_file):
    # 读取part4分数为0的记录
    part4_score0_list = select_score0_from_csv(csv_file, 'score_ai_part_4')
    print("len of part4_score0_list:", len(part4_score0_list))
    # todo 读取每个文件part4的图片和文字
    # part4_score0_list = part4_score0_list[:3]
    for part4_score0 in part4_score0_list:
        print(part4_score0["file_path"], part4_score0["score_ai_part_4"])
        copy_file_to_directory(part4_score0["file_path"], "E://project/pycharm/vrlab_ai_score/files/part4_score0/")
        print("-------------------------------------------------------------")


def process_part6(csv_file):
    # 读取part6分数为0的记录
    part6_score0_list = select_score0_from_csv(csv_file, 'score_ai_part_6')
    print("len of part6_score0_list:", len(part6_score0_list))
    # part6_score0_list = part6_score0_list[:2]
    for part6_score0 in part6_score0_list:
        file_path = part6_score0["file_path"]
        print(file_path, part6_score0["score_ai_part_6"])
        # 读取每个文件part6文字
        dict_matched_paragraphs = None
        if file_path.lower().endswith('.pdf'):
            extractor = PdfExtractor(file_path)
            extractor.extract_paragraphs()
            dict_matched_paragraphs = extractor.get_matched_paragraphs()
        elif file_path.lower().endswith('.docx'):
            extractor = DocxExtractor(file_path)
            extractor.extract_paragraphs()
            dict_matched_paragraphs = extractor.get_matched_paragraphs()
        else:
            continue
        # 保存到 word
        if dict_matched_paragraphs is not None:
            save_paragraphs_2_docx("files/part6_score0.docx",
                                   dict_matched_paragraphs["6实验结果分析"]["word"],
                                   file_path)
        print("-------------------------------------------------------------")


def process_partX_all(csv_file, csv_col_name, path_save_docx, start_heading, end_heading):
    # 读取part6分数为0的记录
    print("csv_col_name:", csv_col_name)
    partX_score0_list = select_score0_from_csv(csv_file, csv_col_name)
    print("len of partX_score0_list:", len(partX_score0_list))
    # partX_score0_list = partX_score0_list[:2]
    for partX_score0 in partX_score0_list:
        file_path = partX_score0["file_path"]
        print(file_path, partX_score0[csv_col_name])
        # todo 读取每个文件part6文字, 保存到 word
        if file_path.lower().endswith('.pdf'):
            extract_and_save_content_pdf(file_path, path_save_docx, start_heading, end_heading, file_path)
        elif file_path.lower().endswith('.docx'):
            extract_and_save_content_docx(file_path, path_save_docx, start_heading, end_heading, file_path)
        else:
            continue
        print("-------------------------------------------------------------")


def process_part7(csv_file):
    # 读取part7分数为0的记录
    part7_score0_list = select_score0_from_csv(csv_file, 'score_ai_part_7')
    print("len of part7_score0_list:", len(part7_score0_list))
    # part7_score0_list = part7_score0_list[:2]
    for part7_score0 in part7_score0_list:
        file_path = part7_score0["file_path"]
        print(file_path, part7_score0["score_ai_part_7"])
        # 读取每个文件part6文字
        dict_matched_paragraphs = None
        if file_path.lower().endswith('.pdf'):
            extractor = PdfExtractor(file_path)
            extractor.extract_paragraphs()
            dict_matched_paragraphs = extractor.get_matched_paragraphs()
        elif file_path.lower().endswith('.docx'):
            extractor = DocxExtractor(file_path)
            extractor.extract_paragraphs()
            dict_matched_paragraphs = extractor.get_matched_paragraphs()
        else:
            continue
        # 保存到 word
        if dict_matched_paragraphs is not None:
            save_paragraphs_2_docx("files/part7_score0.docx",
                                   dict_matched_paragraphs["7实验结论"]["word"],
                                   file_path)
        print("-------------------------------------------------------------")


def main():
    csv_file = 'files/result/test_back_score5_v2.csv'
    # process_part6(csv_file)
    # process_part7(csv_file)
    process_partX_all(csv_file, 'score_ai_part_3', "files/part3_score0_all.docx", "集成电路设计实验结果", "集成电路制造实验结果")
    process_partX_all(csv_file, 'score_ai_part_4', "files/part4_score0_all.docx", "集成电路制造实验结果", "集成电路封装与测试实验结果")
    process_partX_all(csv_file, 'score_ai_part_5', "files/part5_score0_all.docx", "集成电路封装与测试实验结果", "实验结果分析")
    process_partX_all(csv_file, 'score_ai_part_6', "files/part6_score0_all.docx", "实验结果分析", "实验结论")
    process_partX_all(csv_file, 'score_ai_part_7', "files/part7_score0_all.docx", "实验结论", "bulabulabula")


if __name__ == '__main__':
    main()